typeof vs instanceof
2017-05-07 23:00:00 # fontend

工作中往往在判断变量类型的时候,会用到 typeof 和 instanceof ,前者在初学时用到的比较多,看过其他人对这两种方法的总结,其实理解并不难,但是好记性不如烂笔头,记录总结也可以更好的学习。

typeof

可用于基本类型的判断,容易混淆的地方有:

1
2
3
4
5
6
7
8
9
10
11
typeof String("abc");   //返回"string"
typeof new String("abc"); //返回”object“

typeof Number(1); //返回"number"
typeof new Number(1); //返回"object"

typeof Boolean(true); //返回"boolean"
typeof new Boolean(true); //返回"object"

typeof null //返回"object" 不要问为什么 这是个bug 注意就行
typeof undefined //返回"undefined"

对于 object 类型,typeof 就不可靠了,所以这里可以用到 instanceof

instanceof

1.可用于比较自定义对象

1
2
3
4
5
6
7
8
9
10
function Foo() {}
function Bar() {}
Bar.prototype = new Foo();

new Bar() instanceof Bar; // true
new Bar() instanceof Foo; // true

// 如果仅仅设置 Bar.prototype 为函数 Foo 本身,而不是 Foo 构造函数的一个实例
Bar.prototype = Foo;
new Bar() instanceof Foo; // false

2.比较内置类型 尤其是 object 特殊类型

1
2
3
4
5
6
7
8
9
10
语法
object instanceof constructor

参数
object 要检测的对象
constructor 构造函数

规则
检查 object 是否继承自 constructor.prototype,返回一个布尔值。
注意:不是判断一个对象的类型
1
2
3
4
5
6
7
new String('foo') instanceof String; // true
new String('foo') instanceof Object; // true

'foo' instanceof String; // false
'foo' instanceof Object; // false

null instanceof Object //false null是一种"原型"数据类型 不是继承自object 因此返回false

跨窗口问题

以上两种类型判断仅限于同一 JavaScript 上下文的对象,不同的文档结构也就是不同的窗口中将会出错,因为他们的构造函数不是同一个实例

那么问题来了,如果是跨上下文环境判断对象可以怎样做呢

toString

toString 方法是最为可靠的类型检测手段,它会将当前对象转换为字符串并输出。 toString 属性定义在 Object.prototype 上,因而所有对象都拥有 toString 方法。 但 Array, Date 等对象会重写从 Object.prototype 继承来的 toString, 所以最好用 Object.prototype.toString 来检测类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(3); // [object Number]
toString.call([]); // [object Array]
toString.call({}); // [object Object]

// Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]

//toString 也不是完美的,它无法检测用户自定义类型。 因为Object.prototype是不知道用户会创造什么类型的, 它只能检测ECMA标准中的那些内置类型。
toString.call(new Animal) // [object Object]

总结

  • typeof 只能检测基本数据类型,对于 null 还有 Bug ;

  • instanceof 适用于检测对象,它是基于原型链运作的;

  • toString 适用于 ECMA 内置 JavaScript 类型(包括基本数据类型和内置对象)的类型判断;

总之,如果你要判断的是基本数据类型或 JavaScript 内置对象,使用toString; 如果要判断的时自定义类型,请使用instanceof